/*
 * Javlov - a Java toolkit for reinforcement learning with multi-agent support.
 * 
 * Copyright (c) 2009 Matthijs Snel
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.world;

import java.util.ArrayList;
import java.util.List;

import net.javlov.util.ObjectFactory;
import net.javlov.util.SAXReader;


import org.jdom.Element;

public class XMLWorldBuilder {

	protected Element configEl;
	
	public World buildWorld() {
		return loadWorld(configEl);
	}
	
	public void load(String configFile) {
		configEl = SAXReader.read(configFile).getRootElement();
	}
	
	public World loadWorld( Element config ) {
		if ( !config.getName().equalsIgnoreCase("world") )
			throw new IllegalArgumentException("Received element with name: " + config.getName()
					+ ", expected: element with name: world");
		
		String	width = config.getAttributeValue("width"),
				height = config.getAttributeValue("height");
		World world;
		
		Element javaClass = config.getChild("javaclass");
		if ( javaClass != null ) {
			world = (World) ObjectFactory.createObject(javaClass);
			configWorld(world, width, height);
		}
		else
			world = getDefaultWorld(width, height);
		
		
		List<Element> objGroupEls = config.getChildren("objectgroup");
		for ( Element el : objGroupEls )
			loadObjectGroup( el, world );
		return world;
	}
	
	protected void loadObjectGroup(Element objGroupEl, World world) {
		List<Element> objEls = objGroupEl.getChildren("object");
		List<Body> bodies = new ArrayList<Body>();
		int type = Integer.parseInt(objGroupEl.getAttributeValue("type"));
		for ( Element el : objEls ) {
			loadObject( el, bodies, world, type );
		}
		configBodyGroup(objGroupEl, bodies, world,
				objGroupEl.getAttributeValue("oninit"),
				objGroupEl.getAttributeValue("onreset"));
	}
	
	protected void loadObject(Element objEl, List<Body> bodies, World w, int type) {
		int number = Integer.parseInt( objEl.getAttributeValue("number") );
		Element javaClass = objEl.getChild("javaclass");
		String 	x = objEl.getAttributeValue("x"),
				y = objEl.getAttributeValue("y"),
				width = objEl.getAttributeValue("width"),
				height = objEl.getAttributeValue("height");
		double reward = Double.parseDouble(objEl.getAttributeValue("reward"));
		Body b;
		for ( int i = 0; i < number; i++ ) {
			if ( javaClass != null)
				b = (Body) ObjectFactory.createObject(javaClass);
			else
				b = getDefaultBody(type);
			configBody(b, x, y, width, height);
			b.setType(type);
			b.setReward(reward);
			bodies.add(b);
			w.addBody(b);
		}
	}
	
	protected void configBody(Body b, String x, String y, String width, String height) {}
	
	protected void configBodyGroup(Element objGroupEl, List<Body> bodies, World w, String onInit, String onReset) {}
	
	protected void configWorld(World w, String width, String height) {}
	
	protected World getDefaultWorld(String width, String height) { return null; }
	
	protected Body getDefaultBody(int type) { return null; }
}
